from openpyxl import Workbook,load_workbook
import datetime
#行列删除后，后面的行列就会补上来，导致检索出问题，需要自己计数，删除就不计数，没删除就计数+1
#列表里很多数据格式，不是python里经常用的，比如datetime，需要type（）看数据类型，根据对应的数据类型找比较直和他做条件判断。

import numpy as np
from openpyxl import Workbook,load_workbook
import pickle
import random
import copy
save_data_dir=r"D:\Personal\Desktop\beifen"
wb = load_workbook('D:/Personal/Desktop/InputData.xlsx', read_only=True)
ws=wb['Pucks']
wc=wb['Gates']

class plane():
    def __init__(self,Fa,Fd,P,A,D,no,name):
        self.Fa = Fa
        self.Fd= Fd
        self.P = P
        self.A = A
        self.D = D
        self.No=no
        self.name=name
class port():
    def __init__(self,Ha,Hd,G,no,name):
        self.Ha = Ha
        self.Hd= Hd
        self.G = G
        self.No=no
        self.S_pl=[]
        self.name=name
def save_pickle_data(save_data_dir, save_data, dataname):
    # 保存数据集
    with open(save_data_dir + "/" + dataname + ".pickle", "wb") as handle:
        # pickle.dump(save_data, handle)
        pickle.dump(save_data, handle, protocol=pickle.HIGHEST_PROTOCOL)
    handle.close()
 
 
def read_pickle_data(save_data_dir, dataname):
    with open(save_data_dir + "/" + dataname + ".pickle", 'rb') as handle:
        read_data = pickle.load(handle)
    handle.close()
    return read_data

def S_T(plane,port):
    if plane.Fa*port.Ha>=0 and plane.Fd*port.Hd>=0 and plane.P-port.G==0:
        return True
    else:
        return False

def F(St,port):
    
    f1=len(St)
    f2=0
    f3=0
    for port_ in port:
        f2+=len(port_.S_pl)/(len(port_.S_pl)+0.00001)

    
    return f1*70+int(f2)

def Sol(planes,ports):
    PLANES=copy.deepcopy(planes)
    PLANES1=copy.deepcopy(planes)
    PORTS1=copy.deepcopy(ports)
    PORTS=copy.deepcopy(ports)
    St=[]
    St1=[]
    de=0
    ST__=[]

    for count in range(len(planes)): 
        PORTS1.clear()
        PORTS.clear()
        PORTS1=copy.deepcopy(ports)
        PORTS=copy.deepcopy(ports)
        St.clear()
        St1.clear()
        for plane_ in PLANES:
            for port_ in PORTS:
               bool1=False
               if S_T(plane_,port_): #约束条件满足
                   if len(port_.S_pl)==0:
                       port_.S_pl.append(plane_)
                       bool1=True
                       break
                   elif plane_.A-port_.S_pl[-1].D-9>=0:
                        port_.S_pl.append(plane_)
                        bool1=True
                        break               
            if bool1:
                pass
            else:
                St.append(plane_)

        St1.append(planes[count-de])
        del PLANES1[count-de]
    
        for plane_ in PLANES1:
            for port_ in PORTS1:
                bool1=False
                if S_T(plane_,port_): #约束条件满足
                    if len(port_.S_pl)==0:
                        port_.S_pl.append(plane_)
                        bool1=True
                        break
                    elif plane_.A-port_.S_pl[-1].D-9>=0:
                        port_.S_pl.append(plane_)
                        bool1=True
                        break
            if bool1:
                pass
            else:
                St1.append(plane_)
            
        if F(ST__+St,PORTS)>=F(ST__+St1,PORTS1):
            value=F(St1+ST__,PORTS1)
            PLANES=copy.deepcopy(PLANES1)
            ports_linshi=copy.deepcopy(PORTS1)
            ST_linshi=copy.deepcopy(St1)
            ST__.append(planes[count-de])
            de+=1
        
        else:
            value=F(St+ST__,PORTS)
            PLANES1=copy.deepcopy(PLANES)
            ports_linshi=copy.deepcopy(PORTS)
            ST_linshi=copy.deepcopy(St)
               
    PORTS=copy.deepcopy(ports_linshi)
    ST=ST__+ST_linshi
    return value,PORTS,ST

##写入数据
#planes=[]
#ports=[]
#for i in range(2,ws.max_row+1):
#    planes.append(plane(ws.cell(i,5).value,ws.cell(i,10).value,ws.cell(i,6).value,ws.cell(i,13).value,ws.cell(i,14).value,i-1,ws.cell(i,1).value))
#    if i<=wc.max_row:
#        ports.append(port(wc.cell(i,4).value,wc.cell(i,5).value,wc.cell(i,6).value,i-1,wc.cell(i,1).value))
#save_pickle_data(save_data_dir,planes,"planes")
#save_pickle_data(save_data_dir,ports,"ports")


#读取数据
planes=read_pickle_data(save_data_dir,"planes")
ports=read_pickle_data(save_data_dir,"ports") #飞机和停机口按属性建类 飞机0-302  303个 。停机口0-68  69个

#循环计算
#value0=10000
T=0 #循环次数
value0,PORTS_resalt,ST_resalt=read_pickle_data(save_data_dir,"登机口结果")
print("读取历史最优值为：",value0)


for T_ in range(T):
    print("第",T_+1,"/",T,"次计算")
    random.shuffle(ports)
    #排序 str.remove(2)
    value,PORTS,ST=Sol(planes,ports)
    if value<value0:
        print("最优值更新为",value)
        value0=value
        PORTS_resalt=copy.deepcopy(PORTS)
        ST_resalt=copy.deepcopy(ST)
        result_save=copy.deepcopy([value0,PORTS_resalt,ST_resalt])
        save_pickle_data(save_data_dir,result_save,"登机口结果")
    PORTS.clear()
    ST.clear()
i1=0
i2=0
i3=0
for p in PORTS_resalt:
    sum=0
    print("登机口",p.No,":",end='')
    if len(p.S_pl)!=0:
        i1+=1
        for pl in p.S_pl:
            print("飞机",pl.No, ";",end='')
            i2+=1

            if pl.D>288*2:
                D=288*2
            else:
                D=pl.D
            if pl.A<288:
                A=288
            else:
                A=pl.A
            sum+=D-A+9
    if (sum-9)/288>0.8:
        i3+=1
    print((sum-9)/288)
print(i3)

print("临时停机口",":",end='')
for s in ST_resalt:
    print("飞机",s.No, ";",end='')
print("\n已使用登机口；",i1,"\n登机口飞机：",i2,"\n临时登机口飞机:",len(ST_resalt),"\n优化值：",value0)
    

    
